package com.common.project.util;


import com.common.project.common.Constants;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class ReflectionUtils {
    private static Pattern linePattern = Pattern.compile("_(\\w)");


    public static Method getMethod(Object obj, String methodName) {
        for (Method m : obj.getClass().getDeclaredMethods()) {
            if (m.getName().equals(methodName)) {
                return m;
            }
        }
        return null;
    }

    /**
     * Bean 转 Map   转完key为驼峰格式
     *
     * @param javaBean
     * @return
     */
    public static Map<String, Object> toMap(Object javaBean) {
        Map<String, Object> result = new HashMap<String, Object>();
        Method[] methods = javaBean.getClass().getDeclaredMethods();

        for (Method method : methods) {
            if (!method.getName().startsWith("get")) {
                continue;
            }
            String field = method.getName();
            field = field.substring(field.indexOf("get") + 3);
            field = lineToHump(camelToUnderline(field));

            try {
                Object value = method.invoke(javaBean, (Object[]) null);
                result.put(field, value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * Bean 转 Map   转完key为非驼峰格式
     *
     * @param javaBean
     * @return
     */
    public static Map<String, Object> toColumnMap(Object javaBean) {
        Map<String, Object> result = new HashMap<String, Object>();
        Method[] methods = javaBean.getClass().getDeclaredMethods();

        for (Method method : methods) {
            if (!method.getName().startsWith("get")) {
                continue;
            }
            String field = method.getName();
            field = field.substring(field.indexOf("get") + 3);
            field = camelToUnderline(field);

            try {
                Object value = method.invoke(javaBean, (Object[]) null);
                result.put(field, value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 下划线转驼峰
     */
    public static String lineToHump(String str) {
        if (org.springframework.util.StringUtils.isEmpty(str)) {
            return str;
        }
        str = str.toLowerCase();
        java.util.regex.Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 驼峰 转 下划线
     *
     * @param param
     * @return
     */
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(Constants.UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }

        if (0 == sb.indexOf(String.valueOf(Constants.UNDERLINE))) {
            return sb.substring(1);
        }

        return sb.toString();
    }


    public static <T>void fatherToChild(T father,T child) throws Exception {
        if (child.getClass().getSuperclass()!=father.getClass()){
            throw new Exception("child 不是 father 的子类");
        }
        Class<?> fatherClass = father.getClass();
        Field[] declaredFields = fatherClass.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            Field field=declaredFields[i];
            Method method=fatherClass.getDeclaredMethod("get"+upperHeadChar(field.getName()));
            Object obj = method.invoke(father);
            field.setAccessible(true);
            field.set(child,obj);
        }

    }

    /**
     * 首字母大写，in:deleteDate，out:DeleteDate
     */
    public static String upperHeadChar(String in) {
        String head = in.substring(0, 1);
        String out = head.toUpperCase() + in.substring(1, in.length());
        return out;
    }


}
